/**************************************************************************//**
 * @item     CosyOS-III Port
 * @file     port_cmx.h
 * @brief    CMSIS Cortex-M Core Port File
 * @author   迟凯峰
 * @version  V1.2.9
 * @date     2025.05.18
 ******************************************************************************/

#ifndef __PORT_CMX_H
#define __PORT_CMX_H

/* INCLUDE */
#include <stdbool.h>
#include "os_base.h"
#include "os_def.h"
#include "syscfg.h"
#include "mcucfg_cm0.h"
#include "mcucfg_cm3.h"
#include SYSCFG_STANDARDHEAD
#include "cmsis_specific.h"


/* Memory */
#define _SYS_MEM_
#define _CODE_MEM_
#define _CONST_MEM_
#define _STACK_MEM_
#define _XDATA_MEM_
#define _STATIC_MEM_
#define _MALLOC_MEM_
#define _OBJ_MEM_
#define _RTC_MEM_
#define _QUE_MEM_
#define _DEBUG_MEM_


/* Register */
#define _SYS_REG_


/* Typedef */
#define m_boolvoid_tf
typedef unsigned long long int s_u64_t;
typedef bool     m_bit_t;
typedef s_u32_t  m_sp_t;
typedef s_u32_t  m_stacksize_t;
typedef s_u32_t  m_tick_t;
typedef s_u32_t  m_pc_t;
typedef s_u32_t  m_fetion_t;
typedef s_u32_t  m_group_t;


/* Extern */
extern  s_u32_t  m_basepri;

#if MCUCFG_PENDSVFIFO_DEPTH > 0
extern  s_u32_t  mPendSV_FIFO_DepthMAX;
extern   void   *mPendSV_FIFO[2][MCUCFG_PENDSVFIFO_DEPTH + 1];
extern   void  **mPendSV_FIFO_P0;
extern   void  **mPendSV_FIFO_P1;
extern   volatile bool m_sign_fifo;
extern   void    mPendSV_FIFOLoader (void *sv);
extern   void    mPendSV_FIFOHandler(void);

#if MCUCFG_PENDSVFIFO_MUTEX == 2
extern   void  **mPendSV_FIFO_P2;
extern   volatile bool m_sign_load;

/*
 * Arm Compiler 4/5
 */
#if defined ( __CC_ARM )
register void ***mPendSV_FIFO_REGx __ASM("r6");

/*
 * Arm Compiler 6.6 LTM / above 6.10.1 (armclang)
 */
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma -ffixed-r6

/*
 * GNU Compiler
 */
#elif defined ( __GNUC__ )
__extension__ register void ***mPendSV_FIFO_REGx __ASM("r6");

/*
 * IAR Compiler
 */
#elif defined ( __ICCARM__ )
/* For IAR compiler, please set --lock_regs=r6, use Project > Options > C/C++ Compiler > Extra Options. */

/*
 * Other Compiler
 */
#else
/* For other compiler, please customize the register variable, or reset option of exclusive access in mcucfg_cmx.h. */
#endif

#endif
#endif


/* CONST & ATTRIBUTE */
#define MCUCFG_ISA                __ARM__
#define MCUCFG_PCLEN              4
#define MCUCFG_C51USING
#define MCUCFG_SYSTICK_ATTRIBUTE
#define MCUCFG_TERNARYMASK

#define MCUCFG_STACK_ALIGN        __ALIGNED(8)
#define MCUCFG_TASKSTACK_REALLOC  __DISABLED__
#if MCUCFG_ASPEN_LSPEN == __ENABLED__
#define MCUCFG_CALLER_PUSH_FPU    (18 * 4) /** \push   {s0-s15,FPSCR,UNKNOW} */
#define MCUCFG_CALLEE_PUSH_FPU    (16 * 4) /** \vstmdb {s16-s31} */
#else
#define MCUCFG_CALLER_PUSH_FPU    0
#define MCUCFG_CALLEE_PUSH_FPU    0
#endif
#define MCUCFG_CALLER_PUSH_REG    (8 * 4)  /** \push   {r0-r3,r12,r14(lr),r15(pc),xPSR} */
#define MCUCFG_CALLEE_PUSH_REG    (8 * 4)  /** \stmdb  {r4-r11} */
#define MCUCFG_CALLER_PUSH        (MCUCFG_CALLER_PUSH_FPU + MCUCFG_CALLER_PUSH_REG)
#define MCUCFG_CALLEE_PUSH        (MCUCFG_CALLEE_PUSH_FPU + MCUCFG_CALLEE_PUSH_REG)
#define MCUCFG_BASICSTACKSIZE     (MCUCFG_CALLER_PUSH + MCUCFG_CALLEE_PUSH)


/* TaskNode */
#define mTaskNode_Head_           m_sp_t psp;
#define mTaskNode_Tail_           m_sp_t psp_top;


/*
 * SysTick
 */
#if MCUCFG_SYSTICK_AUTOCONFIG == __ENABLED__
/* 自动配置 */
#define MCUCFG_SYSTICK_COUNTMODE   2             /*!< 计数方式，2：从重装载值向下计数至零溢出 */
#define MCUCFG_SYSTICK_LIMITVALUE (1UL << 24)    /*!< 极限值 */
#define MCUCFG_SYSTICK_CURRVALUE  (SysTick->VAL) /*!< 当前值寄存器 */
#define MCUCFG_SYSTICK_CLKDIV     (MCUCFG_SYSTICK_CLKSOURCE ? 1 : 8)
#define MCUCFG_SYSTICK_CLK        (MCUCFG_SYSCLK / MCUCFG_SYSTICK_CLKDIV)
#define MCUCFG_SYSTICK_COUNT1CYC  (SYSCFG_SYSTICK_CYCLE * MCUCFG_SYSTICK_CLK * 1UL)
#define MCUCFG_SYSTICK_LOADVALUE  (MCUCFG_SYSTICK_COUNT1CYC - 1)
#define MCUCFG_SYSTICK_MAXVALUE    MCUCFG_SYSTICK_LOADVALUE
#define MCUCFG_SYSTICK_MINVALUE    0
#if (MCUCFG_SYSCLK % MCUCFG_SYSTICK_CLKDIV)
#warning 系统滴答时钟不为整数。
#endif
#if (MCUCFG_SYSTICK_COUNT1CYC > MCUCFG_SYSTICK_LIMITVALUE)
#error 系统滴答定时器溢出。
#endif
#define mSysTick_SetLOAD()        SysTick->LOAD = MCUCFG_SYSTICK_LOADVALUE
#define mSysTick_SetCTRL()        SysTick->CTRL = ((MCUCFG_SYSTICK_CLKSOURCE ? 0x04 : 0x00) | 0x02 | 0x01)
#define mSysTick_INIT() \
do{ \
	mSysTick_SetPRI(); \
	mSysTick_SetLOAD(); \
	mSysTick_SetCTRL(); \
}while(false)

#else
/* 手动配置 */
#if   MCUCFG_SYSTICK_COUNTMODE == 1 \
   || MCUCFG_SYSTICK_COUNTMODE == 2
#define MCUCFG_SYSTICK_MAXVALUE   (MCUCFG_SYSTICK_LOADVALUE)
#define MCUCFG_SYSTICK_MINVALUE   0
#define MCUCFG_SYSTICK_COUNT1CYC  (MCUCFG_SYSTICK_LOADVALUE + 1UL)

#elif MCUCFG_SYSTICK_COUNTMODE == 3 \
   || MCUCFG_SYSTICK_COUNTMODE == 4
#define MCUCFG_SYSTICK_LIMITVALUE (1UL << MCUCFG_SYSTICK_BITS)
#define MCUCFG_SYSTICK_MAXVALUE   (MCUCFG_SYSTICK_LIMITVALUE)
#define MCUCFG_SYSTICK_MINVALUE   (MCUCFG_SYSTICK_LOADVALUE)
#define MCUCFG_SYSTICK_COUNT1CYC  (MCUCFG_SYSTICK_MAXVALUE - MCUCFG_SYSTICK_MINVALUE)
#endif

#define mSysTick_INIT()  mSysTick_SetPRI()
#endif


/*
 * SysTick_Handler + PendSV_Handler
 */
#if MCUCFG_SYSINT == 3
/* SysTick */
#define mSysTick_SetPRI() *(volatile s_u8_t  *)0xE000ED23 = 0xFF

/* PendSV */
#define mPendSV_SetPRI()  *(volatile s_u8_t  *)0xE000ED22 = 0xFF
#define mPendSV_Set()     *(volatile s_u32_t *)0xE000ED04 = 0x10000000
#define mPendSV_Clear()
#define mPendSV_INIT() \
do{ \
	mPendSV_SetPRI(); \
	m_basepri <<= 7 - ((*(volatile s_u32_t *)0xE000ED00 >> 8) & 7); \
	m_basepri--; \
	m_basepri <<= 1 + ((*(volatile s_u32_t *)0xE000ED00 >> 8) & 7); \
}while(false)

/* 内核锁 */
__STATIC_FORCEINLINE void __mu_disable_sysirq(void)
{
	__set_BASEPRI(m_basepri);
	__ASM("dsb");
	__ASM("isb");
}

#define mSysIRQ_Disable() __mu_disable_sysirq()
#define mSysIRQ_Enable()  __set_BASEPRI(0)


/*
 * TIMn_IRQHandler + XXXx_IRQHandler
 */
#elif MCUCFG_SYSINT == 0
/* SysTick */
#define mSysTick_SetPRI() \
	*(volatile s_u32_t *)(0xE000E400 + MCUCFG_TIMn_IRQn /  4 * 4)|= 0xFFUL << (MCUCFG_TIMn_IRQn %  4) * 8

/* PendSV */
#define mPendSV_SetPRI() \
	*(volatile s_u32_t *)(0xE000E400 + MCUCFG_XXXx_IRQn /  4 * 4)|= 0xFFUL << (MCUCFG_XXXx_IRQn %  4) * 8

#define mPendSV_Set() \
	*(volatile s_u32_t *)(0xE000E200 + MCUCFG_XXXx_IRQn / 32 * 4) = 0x01UL << (MCUCFG_XXXx_IRQn % 32)
/*
#define mPendSV_Clear() \
	*(volatile s_u32_t *)(0xE000E280 + MCUCFG_XXXx_IRQn / 32 * 4) = 0x01UL << (MCUCFG_XXXx_IRQn % 32)
*/
#define mPendSV_Clear()

#define mPendSV_INIT() \
do{ \
	mPendSV_SetPRI(); \
	m_basepri = 1 + ((*(volatile s_u32_t *)0xE000ED00 >> 8) & 7); \
}while(false)

/* 内核锁 */
#define mSysINT_Disable() \
	*(volatile s_u32_t *)(0xE000E180 + MCUCFG_XXXx_IRQn / 32 * 4) = (0x01UL << (MCUCFG_XXXx_IRQn % 32)) \
                                                                  | (0x01UL << (MCUCFG_TIMn_IRQn % 32))
#define mSysINT_Enable() \
	*(volatile s_u32_t *)(0xE000E100 + MCUCFG_XXXx_IRQn / 32 * 4) = (0x01UL << (MCUCFG_XXXx_IRQn % 32)) \
                                                                  | (0x01UL << (MCUCFG_TIMn_IRQn % 32))
__STATIC_FORCEINLINE void __mu_disable_sysirq(void)
{
	mSysINT_Disable();
	__ASM("dsb");
	__ASM("isb");
}

__STATIC_FORCEINLINE void __mu_enable_sysirq(void)
{
	mSysINT_Enable();
}

#define mSysIRQ_Disable() __mu_disable_sysirq()
#define mSysIRQ_Enable()  __mu_enable_sysirq()
#endif


/* CCR：栈8字节对齐 */
#define mCCR_Set() \
do{ \
	*(volatile s_u32_t *)0xE000ED14 |= 0x0200; \
}while(false)


/*
 * FPU
 */

/* CPACR: CP11|CP10 */
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) \
 &&  (defined (__FPU_USED   ) && (__FPU_USED    == 1U)))
#define mCPACR_Set() \
do{ \
	*(volatile s_u32_t *)0xE000ED88 |= (0x0FUL << 20); \
	__ASM("dsb"); \
}while(false)
#else
#define mCPACR_Set()
#endif

/* FPCCR: ASPEN|LSPEN */
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) \
 &&  (defined (__FPU_USED   ) && (__FPU_USED    == 1U)))
#if MCUCFG_ASPEN_LSPEN == 1
#define mFPCCR_Set() \
do{ \
	*(volatile s_u32_t *)0xE000EF34 |= (0x03UL << 30); \
	__ASM("isb"); \
}while(false)
#else
#define mFPCCR_Set() \
do{ \
	*(volatile s_u32_t *)0xE000EF34 &=~(0x03UL << 30); \
	__ASM("isb"); \
}while(false)
#endif
#else
#define mFPCCR_Set()
#endif

/* FPSCR */
#if MCUCFG_ASPEN_LSPEN == 1 \
 && ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) \
 &&  (defined (__FPU_USED   ) && (__FPU_USED    == 1U)))
#define mFPSCR_INIT() \
do{ \
	*(volatile s_u32_t *)(node_news->psp - 8) = __get_FPSCR(); \
}while(false)
#else
#define mFPSCR_INIT()
#endif


/* CosyOS初始化 */
#define mCosyOS_INIT() \
do{ \
	__set_PSP(__get_MSP() - 2 * MCUCFG_BASICSTACKSIZE); \
	__set_CONTROL(0x02); \
	mCCR_Set(); \
	mCPACR_Set(); \
	mFPCCR_Set(); \
	mPendSV_INIT(); \
	mSysTick_INIT(); \
	mSysIRQ_Enable(); \
	__ASM("cpsie i"); \
}while(false)


/* CosyOS低功耗 */
#define mCosyOS_IDLE()  __WFI()


/* 中断挂起服务_FIFO */
#define mPendSV_FIFOLoad() \
do{ \
	mPendSV_FIFOLoader(&u_psv); \
	mPendSV_Set(); \
}while(false)

#define mPendSV_FIFOHandle() \
	if(mPendSV_FIFO_P0 > mPendSV_FIFO[0]) mPendSV_FIFOHandler()


/* 事件标志组-中断中写多标志位 */
#define miWriteFlagBits() \
	if(!u_psv.value){ \
		do{}while(false)


/* 任务栈 */
#define mTaskStack_LEN() \
	s_taskstacklen = s_task_current->psp_top - __get_PSP() + MCUCFG_CALLEE_PUSH

#define mTaskStack_INIT() \
do{ \
	node_news->psp_top = (m_sp_t)node_news->bsp + node_news->stacksize; \
	if(node_news->psp_top % 8){ \
		node_news->psp_top /= 8; \
		node_news->psp_top *= 8; \
		node_news->stacksize = node_news->psp_top - (m_sp_t)node_news->bsp; \
	} \
	node_news->psp = node_news->psp_top; \
	mFPSCR_INIT(); /* FPSCR */ \
	*(volatile s_u32_t *)(node_news->psp - MCUCFG_CALLER_PUSH_FPU - 4) = 0x01000000; /* xPSR */ \
	*(volatile s_u32_t *)(node_news->psp - MCUCFG_CALLER_PUSH_FPU - 8) = (s_u32_t)s_task_starter->entry; /* r15(pc) */ \
	node_news->psp -= MCUCFG_BASICSTACKSIZE; \
}while(false)


/* 全局临界区 */
__STATIC_INLINE s_u32_t __mx_disable_irq(void)
{
	register s_u32_t oldirq = __get_PRIMASK();
	__ASM("cpsid i");
	__ASM("nop");
	return oldirq;
}

#define mxDisableIRQ()            __mx_disable_irq()
#define mxResumeIRQ(oldirq)       __set_PRIMASK(oldirq)

#if (MCUCFG_SYSINT == 0) \
 && ((defined (__ARM_ARCH_7M__       ) && (__ARM_ARCH_7M__        == 1)) \
 ||  (defined (__ARM_ARCH_7EM__      ) && (__ARM_ARCH_7EM__       == 1)) \
 ||  (defined (__ARM_ARCH_8M_MAIN__  ) && (__ARM_ARCH_8M_MAIN__   == 1)) \
 ||  (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)))
__STATIC_INLINE s_u32_t __mx_masking_pri(s_u32_t newpri)
{
	register s_u32_t oldpri = __get_BASEPRI();
	__set_BASEPRI_MAX(newpri << m_basepri);
	__ASM("dsb");
	__ASM("isb");
	return oldpri;
}

#define mxMaskingPRI(newpri)      __mx_masking_pri(newpri)
#define mxResumePRI(oldpri)       __set_BASEPRI(oldpri)
#endif


#endif
